package global

import (
	"fmt"
	"os"
	"path"
	"time"

	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type LogConfig struct {
	Level   string `yaml:"level"`
	Path    string `yaml:"path"`
	MaxSize uint   `yaml:"save"`
}

var Log *zap.SugaredLogger
var ZapLogger *zap.Logger

func InitLogger() {
	if ZapLogger == nil {
		encoder := GetEncoder()
		cores := make([]zapcore.Core, 0)

		// 调试级别
		debugPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
			return lev == zap.DebugLevel
		})
		// 日志级别
		infoPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
			return lev == zap.InfoLevel
		})
		// 警告级别
		warnPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
			return lev == zap.WarnLevel
		})
		// 错误级别
		errorPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
			return lev >= zap.ErrorLevel
		})
		debug := Config.GetInt("sys.debug")
		if debug == 1 {
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), debugPriority))
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), infoPriority))
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), warnPriority))
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), errorPriority))
		} else {
			// 生产环境下 INFO + DEBUG不记录
			//cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(getLogWriter(fmt.Sprintf("%s_debug", AppName))), debugPriority))
			//cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(getLogWriter(fmt.Sprintf("%s_info", AppName))), infoPriority))
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(getLogWriter(fmt.Sprintf("%s_warn", AppName))), warnPriority))
			cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(getLogWriter(fmt.Sprintf("%s_error", AppName))), errorPriority))
		}
		core := zapcore.NewTee(cores...)
		ZapLogger = zap.New(core, zap.AddCaller())
		Log = ZapLogger.Sugar()
	}
}

func InitGormLogger(dbName string) *zap.Logger {
	encoder := GetEncoder()
	logWriter := getLogWriter(fmt.Sprintf("%s_%s_mysql", AppName, dbName))
	cores := make([]zapcore.Core, 0)
	cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(logWriter), zap.InfoLevel))
	debug := Config.GetInt("sys.debug")
	if debug == 1 {
		cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zap.DebugLevel))
	}
	core := zapcore.NewTee(cores...)
	return zap.New(core, zap.AddCaller())
}

func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format("[2006-01-02 15:04:05]"))
}

func GetEncoder() zapcore.Encoder {
	zapType := Config.GetString("zap.mod")
	var encoderConfig zapcore.EncoderConfig
	switch zapType {
	case "prod":
		encoderConfig = zap.NewProductionEncoderConfig()
	case "debug":
		encoderConfig = zap.NewDevelopmentEncoderConfig()
	}

	encoderConfig.EncodeTime = customTimeEncoder            // 时间
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 按级别显示不同颜色，不需要的话取值zapcore.CapitalLevelEncoder就可以了
	encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder // 显示完整文件路径
	return zapcore.NewConsoleEncoder(encoderConfig)
}

func getLogWriter(logType string) zapcore.WriteSyncer {
	filename := path.Join(Config.GetString("zap.path"), logType)

	lumberJackLogger := &lumberjack.Logger{
		Filename:   fmt.Sprintf("%s.log", filename), // 日志文件存放目录，如果文件夹不存在会自动创建
		MaxSize:    Config.GetInt("zap.maxSize"),    // 文件大小限制,单位MB
		MaxBackups: Config.GetInt("zap.maxBackups"), // 最大保留日志文件数量
		MaxAge:     Config.GetInt("zap.maxAge"),     // 日志文件保留天数
		Compress:   Config.GetBool("zap.compress"),  // 是否压缩处理
	}
	return zapcore.AddSync(lumberJackLogger)
}

/**
@Create July 19 2022 Enzo
*/
//一边打log一边返回一个error
func LogAndErrorf(format string, a ...interface{}) error {
	Log.Warnf(format, a...)
	return fmt.Errorf(format, a...)
}
